use std::collections::HashMap;
use std::sync::{Arc, Mutex, RwLock};
use lazy_static::lazy_static;

pub struct LiveObs {
    observer: fn(String)
}

pub struct LiveBus {
    observer_map: Arc<RwLock<HashMap<LiveDataParam, LiveObs>>>
}

impl LiveBus {
    fn new() -> Arc<Mutex<Self>> {
        Arc::new(Mutex::new(Self {
            observer_map: Arc::new(RwLock::new(HashMap::new()))
        }))
    }

    pub fn get_instance() -> Arc<Mutex<Self>>{
        static mut INSTANCE: Option<Arc<Mutex<LiveBus>>> = None;

        unsafe {
            INSTANCE.get_or_insert_with(||{
                Self::new()
            }).clone()
        }
    }

    pub fn send_data(&self, key:LiveDataParam, data:&str) {
      match self.observer_map.clone().read().unwrap().get(&key) {
          Some(value) => {
              (value.observer)(data.to_string());
          },
          None => {}
      }
    }

    pub fn observer(&self,key:LiveDataParam,obs:fn(String)) {
        self.observer_map.clone().write().unwrap().insert(key, LiveObs{observer:obs});
    }
}

#[derive(Eq, Hash, Debug, PartialEq)]
pub enum LiveDataParam {
    MYTEST,
}


pub struct LiveBusSync {
    observer_map: HashMap<LiveDataParam, LiveObs>
}

lazy_static!{
    static ref INSTANSE: Mutex<LiveBusSync> = Mutex::new(LiveBusSync{observer_map:HashMap::new()});
}

impl LiveBusSync{

    pub fn get_instance() ->  &'static Mutex<LiveBusSync>{
        return &INSTANSE;
    }

    pub fn send(&self, key:LiveDataParam, data:&str) {
        match  self.observer_map.get(&key) {
            Some(value) => {
                (value.observer)(data.to_string())
            },
            None =>{}
        }
    }

    pub fn observer(&mut self, key:LiveDataParam, obs:fn(String)){
        self.observer_map.insert(key, LiveObs{observer:obs});
    }
}















